using System;
using System.Collections.Generic;

namespace AutoChess
{
    class BEventDispatcher
    {
        private Dictionary<int,List<Delegate>> m_allEventCallBack = new Dictionary<int, List<Delegate>>();
       
        public void Send(int listenerId)
        {
            List<Delegate> listener;
            if (m_allEventCallBack.TryGetValue(listenerId, out listener))
            {
                int count = listener.Count;
                for (int i = 0; i < count; i++)
                {
                    Action callback = listener[i] as Action;
                    if (callback != null)
                    {
                        callback();
                    }
                    else
                    {
                        BLogger.EditorFatal("Invalid GameEvent data type: {0}",callback);
                    }
                }
            }
        }
        
        public void Send<T>(int listenerId,T data)
        {
            List<Delegate> listener;
            if (m_allEventCallBack.TryGetValue(listenerId, out listener))
            {
                int count = listener.Count;
                for (int i = 0; i < count; i++)
                {
                    Action<T> callback = listener[i] as Action<T>;
                    if (callback != null)
                    {
                        callback(data);
                    }
                    else
                    {
                        BLogger.EditorFatal("Invalid GameEvent data type: {0}",callback);
                    }
                }
            }
        }
        
        public void Send<T,U>(int listenerId,T dataT,U dataU)
        {
            List<Delegate> listener;
            if (m_allEventCallBack.TryGetValue(listenerId, out listener))
            {
                int count = listener.Count;
                for (int i = 0; i < count; i++)
                {
                    Action<T,U> callback = listener[i] as Action<T,U>;
                    if (callback != null)
                    {
                        callback(dataT,dataU);
                    }
                    else
                    {
                        BLogger.EditorFatal("Invalid GameEvent data type: {0}",callback);
                    }
                }
            }
        }
        
        public void Send<T,U,V>(int listenerId,T data,U dataU,V dataV)
        {
            List<Delegate> listener;
            if (m_allEventCallBack.TryGetValue(listenerId, out listener))
            {
                int count = listener.Count;
                for (int i = 0; i < count; i++)
                {
                    Action<T,U,V> callback = listener[i] as Action<T,U,V>;
                    if (callback != null)
                    {
                        callback(data,dataU,dataV);
                    }
                    else
                    {
                        BLogger.EditorFatal("Invalid GameEvent data type: {0}",callback);
                    }
                }
            }
        }

        public void AddListener(int listenerId, Action listener)
        {
            AddListenerImp(listenerId, listener);
        }
        
        public void AddListener<T>(int listenerId, Action<T> listener)
        {
            AddListenerImp(listenerId, listener);
        }
        
        public void AddListener<T,U>(int listenerId, Action<T,U> listener)
        {
            AddListenerImp(listenerId, listener);
        }
        
        public void AddListener<T,U,V>(int listenerId, Action<T,U,V> listener)
        {
            AddListenerImp(listenerId, listener);
        }
        
        public void AddListenerImp(int listenerId, Delegate listener)
        {
            List<Delegate> lster;
            if (!m_allEventCallBack.TryGetValue(listenerId, out lster))
            {
                lster = new List<Delegate>();
                m_allEventCallBack.Add(listenerId,lster);
            }

            var existNode = lster.Find((node) => { return node == listener; });
            if (existNode != null)
            {
                BLogger.EditorFatal("AddEvent hashId repeated: {0}",listener);
                return;
            }
            lster.Add(listener);
        }

        public T Get<T>()
        {
            throw new NotImplementedException();
        }
    }
}